package com.mlnx.work.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mlnx.common.entity.Response;
import com.mlnx.common.form.PageForm;
import com.mlnx.work.config.ControllerNames;
import com.mlnx.work.entity.*;
import com.mlnx.work.enums.ProjectStatusEnum;
import com.mlnx.work.enums.ResponseEnum;
import com.mlnx.work.exception.WorkServiceException;
import com.mlnx.work.pojo.form.*;
import com.mlnx.work.pojo.vo.ProjectTaskListVO;
import com.mlnx.work.pojo.vo.ProjectVO;
import com.mlnx.work.service.*;
import com.mlnx.work.utils.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.shan.spring.base.BaseController;
import org.shan.spring.base.annotations.SysLog;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

@Api(value = ControllerNames.ProjectName + "接口", tags = {ControllerNames.ProjectName + "接口"})
@SysLog(title = ControllerNames.ProjectName)
@RestController
@RequestMapping("/project")
public class ProjectController extends BaseController {
    @Autowired
    private ProjectDirService projectDirService;
    @Autowired
    private ProjectTaskService projectTaskService;
    @Autowired
    private ProjectOverdueService projectOverdueService;
    @Autowired
    private ProjectArrangeService projectArrangeService;
    @Autowired
    private ProjectMemberService projectMemberService;
    @Autowired
    private ProjectOverdueExplainService projectOverdueExplainService;

    @ApiOperation("创建项目层级目录")
    @PostMapping("")
    @Transactional
    public Response createProjectDir(@Valid ProjectForm projectForm) {
        List<Right> rights = projectDirService.getRights();
        boolean createRight = false;
        for (Right right : rights) {
            if ("right_create_project".equals(right.getRightKey())) {
                createRight = true;
                break;
            }
        }
        if (!createRight)
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);


        //判断是否当前负责人
        if (projectForm.getParentId() > 0) {
            ProjectDir projectDir = projectDirService.getById(projectForm.getParentId());
            if (projectDir == null || projectDir.getManagerId().intValue() != projectForm.getCreatorId().intValue()) {
                throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
            }
        }
        ProjectDir projectDir = new ProjectDir();
        BeanUtils.copyProperties(projectForm, projectDir);
        projectDir.setCreateTime(System.currentTimeMillis());
        projectDir.setStartTime(0L);
        projectDir.setCompletedTime(0L);
        projectDir.setRisk("");
        projectDir.setStatus(ProjectStatusEnum.ING);
        projectDirService.save(projectDir);
        //判断是否创建根目录，记录rootId为本身id
        if (projectForm.getRootId() == 0) {
            projectDir.setRootId(projectDir.getId());
            try {
                projectDirService.updateById(projectDir);
            } catch (Exception e) {
                logger.error("更新项目层级所属根目录异常");
                throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
            }
        }

        try {
            projectMemberService.saveBatch(projectDir.getId(), projectForm.getMemberIds());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("创建项目参与人员关联记录异常");
            throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
        }

        return result(projectDir.getId());
    }

    @ApiOperation("添加项目参与人员")
    @PostMapping("/member/{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true),
            @ApiImplicitParam(name = "memberIds", value = "参与人ID集合", required = true)
    })
    @Transactional
    public Response addProjectMember(@PathVariable Integer dirId, @RequestParam Integer managerId, @RequestParam Integer[] memberIds) {
        ProjectDir projectDir = projectDirService.getById(dirId);
        if (projectDir == null || projectDir.getManagerId().intValue() != managerId.intValue()) {
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
        }

        projectMemberService.saveBatch(dirId, memberIds);

        return result();
    }

    @ApiOperation("添加项目逾期")
    @PostMapping("/overdue")
    @Transactional
    public Response addProjectOverdue(@Valid OverdueForm overdueForm) {
        ProjectDir projectDir = projectDirService.getById(overdueForm.getId());
        if (DateUtil.dateCompare(overdueForm.getOverdueTime(), projectDir.getOriginEndTime()) < 1) {
            throw new WorkServiceException(ResponseEnum.INVALID_OVERDUE);
        }
        ProjectOverdue projectOverdue = new ProjectOverdue();
        BeanUtils.copyProperties(overdueForm, projectOverdue);
        projectOverdue.setDirId(overdueForm.getId());
        projectOverdue.setCommitTime(System.currentTimeMillis());
        projectOverdueService.save(projectOverdue);
        List<OverdueExplainForm> overdueDescription = overdueForm.getOverdueDescription();
        for(OverdueExplainForm overdueExplain : overdueDescription){
            if (DateUtil.dateCompare(projectOverdue.getOverdueTime(), overdueExplain.getOverdueTime()) < 1) {
                throw new WorkServiceException(ResponseEnum.OVERDUE_TIME_OVER);//逾期计划说明最大时间不能超过项目逾期时间
            }
            ProjectOverdueExplain projectOverdueExplain = new ProjectOverdueExplain();
            BeanUtils.copyProperties(overdueExplain, projectOverdueExplain);
            projectOverdueExplain.setParentId(projectOverdue.getId());
            projectOverdueExplain.setCommitTime(System.currentTimeMillis());
            projectOverdueExplainService.save(projectOverdueExplain);
        }
        return result();
    }
//    @ApiOperation("添加项目逾期说明")
//    @PostMapping("/overdueExplain")
//    @Transactional
//    public Response addProjectOverdueExplain(@Valid OverdueExplainForm overdueExplainForm) {
//        ProjectOverdue projectOverdue = projectOverdueService.getById(overdueExplainForm.getId());
//        if (DateUtil.dateCompare(projectOverdue.getOverdueTime(), overdueExplainForm.getOverdueTime()) < 1) {
//            throw new WorkServiceException(ResponseEnum.OVERDUE_TIME_OVER);//逾期计划说明最大时间不能超过项目逾期时间
//        }
//        ProjectOverdueExplain projectOverdueExplain = new ProjectOverdueExplain();
//        BeanUtils.copyProperties(overdueExplainForm, projectOverdueExplain);
//        projectOverdueExplain.setParentId(overdueExplainForm.getId());
//        projectOverdueExplain.setCommitTime(System.currentTimeMillis());
//        projectOverdueExplainService.save(projectOverdueExplain);
//        return result();
//    }

    @ApiOperation("添加项目周计划")
    @PostMapping("/arrange")
    public Response addProjectArrange(@Valid ArrangeForm arrangeForm) {
        ProjectArrange projectArrange = new ProjectArrange();
        BeanUtils.copyProperties(arrangeForm, projectArrange);
        projectArrange.setDirId(arrangeForm.getId());
        projectArrange.setCommitTime(System.currentTimeMillis());
        projectArrangeService.save(projectArrange);
        return result();
    }

    @ApiOperation("获取项目成员列表")
    @GetMapping("/member/{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true)
    })
    public Response getProjectMember(@PathVariable Integer dirId) {
        return result(projectDirService.getMemberById(dirId));
    }

    @ApiOperation("获取参与项目列表")
    @GetMapping("/list/{memberId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "memberId", value = "成员ID", required = true)
    })
    public Response getProjectList(@PathVariable Integer memberId) {
        return result(projectDirService.getProjectListByMember(memberId));
    }

    @ApiOperation("获取项目层级目录")
    @GetMapping("/{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true)
    })
    public Response getProjectById(@PathVariable Integer dirId) {
        return result(projectDirService.getProjectById(dirId));
    }

    @ApiOperation("获取项目详情")
    @GetMapping("/detail/{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true)
    })
    public Response getProjectDetail(@PathVariable Integer dirId) {
        return result(projectDirService.getProjectDetailById(dirId));
    }

    @ApiOperation("获取项目下任务列表")
    @GetMapping("/parent/task/list/{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true)
    })
    public Response getParentTaskByDirId(@PathVariable Integer dirId, @Valid PageForm pageForm) {
        return result(projectTaskService.getParentTaskByDirId(dirId, pageForm));
    }

    @ApiOperation("设置项目风险项")
    @PutMapping("/risk/{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true),
            @ApiImplicitParam(name = "risk", value = "风险项", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true)
    })
    public Response setProjectRisk(@PathVariable Integer dirId, @RequestParam String risk, @RequestParam Integer managerId) {
        ProjectDir projectDir = projectDirService.getById(dirId);
        if (projectDir.getManagerId().intValue() != managerId.intValue())
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
        projectDir = new ProjectDir();
        projectDir.setId(dirId);
        projectDir.setRisk(risk);
        projectDirService.updateById(projectDir);
        return result();
    }

    @ApiOperation("设置项目实际开始时间")
    @PutMapping("/startTime/{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true),
            @ApiImplicitParam(name = "startTime", value = "项目实际开始时间", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true)
    })
    public Response setProjectStartTime(@PathVariable Integer dirId, @RequestParam Long startTime, @RequestParam Integer managerId) {
        ProjectDir projectDir = projectDirService.getById(dirId);
        if (projectDir.getStartTime() > 0)
            throw new WorkServiceException(ResponseEnum.START_TIME_SET_ALREADY);

        if (projectDir.getManagerId().intValue() != managerId.intValue())
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);

        projectDir = new ProjectDir();
        projectDir.setId(dirId);
        projectDir.setStartTime(startTime);

        projectDirService.updateById(projectDir);
        return result();
    }

    @ApiOperation("提交项目完成")
    @PutMapping("{dirId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "项目层级ID", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true)
    })
    public Response setProjectRisk(@PathVariable Integer dirId, @RequestParam Integer managerId) {
        ProjectDir projectDir = projectDirService.getById(dirId);
        if (projectDir.getManagerId().intValue() != managerId.intValue())
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);


        //判断层级下任务是否全部完成
        Page<ProjectTaskListVO> projectTaskPage = projectTaskService.getParentTaskByDirId(dirId, new PageForm(1L, 10000L));
        if (projectTaskPage.getRecords() != null) {
            for (ProjectTaskListVO projectTaskListVO : projectTaskPage.getRecords()) {
                if (!ProjectStatusEnum.DONE.getStatus().equals(projectTaskListVO.getStatus())) {
                    throw new WorkServiceException(ResponseEnum.CHILD_NOT_COMPLETED);
                }
            }
        }

        //判断层级下层级是否全部完成
        ProjectVO projectVO = projectDirService.getProjectById(dirId);
        if (projectVO.getChildProjectVO() != null) {
            for (ProjectVO childProjectVO : projectVO.getChildProjectVO()) {
                if (!ProjectStatusEnum.DONE.getStatus().equals(childProjectVO.getStatus())) {
                    throw new WorkServiceException(ResponseEnum.CHILD_NOT_COMPLETED);
                }
            }
        }

        projectDir = new ProjectDir();
        projectDir.setId(dirId);
        projectDir.setStatus(ProjectStatusEnum.DONE);
        projectDir.setCompletedTime(System.currentTimeMillis());
        projectDirService.updateById(projectDir);
        return result();
    }

    @ApiOperation("获取项目展示")
    @GetMapping("/report")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = false),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = false)
    })
    public Response getProjectTask(@RequestParam(required = false) Long startTime, @RequestParam(required = false) Long endTime,
                                   @Valid PageForm pageForm, @Valid ProjectFilterForm projectFilterForm) {
        return result(projectDirService.getProjectTask(startTime, endTime, pageForm, projectFilterForm));
    }

    @ApiOperation("获取项目展示根目录")
    @GetMapping("/root")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = false),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = false)
    })
    public Response getProjectRoot(@RequestParam(required = false) Long startTime, @RequestParam(required = false) Long endTime,
                                   @Valid PageForm pageForm) {
        return result(projectDirService.getProjectRoot(startTime, endTime, pageForm));
    }

    @ApiOperation("获取项目展示子层级")
    @GetMapping("/dir")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dirId", value = "层级ID", required = true)
    })
    public Response getProjectDir(@RequestParam Integer dirId, @Valid PageForm pageForm) {
        return result(projectDirService.getProjectDir(dirId, pageForm));
    }

    @ApiOperation("获取项目展示子任务")
    @GetMapping("/task")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true)
    })
    public Response getProjectTask(@RequestParam Integer taskId, @Valid PageForm pageForm) {
        return result(projectDirService.getProjectTask(taskId, pageForm));
    }

    @ApiOperation("报表筛选")
    @GetMapping("/selection")
    public Response projectFilter(@Valid PageForm pageForm, @Valid FilterForm filterForm) {
        return result(projectDirService.projectFilter(pageForm, filterForm));
    }
}
